/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package laba8;


import junit.framework.JUnit4TestAdapter;
 import junit.framework.TestSuite;
 import org.objectweb.asm.ClassReader;
 import org.objectweb.asm.ClassWriter;
 
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.File;
 import java.lang.reflect.Field;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;


 
 public class Utils {
     private static boolean isInterface(Class baseInterface,
             List<Class> interfaces) {
         for (Class item : interfaces) {
             if (baseInterface.equals(item)
                     || isInterface(baseInterface, Arrays.asList(item
                             .getInterfaces())))
                 return true;
         }
         return false;
     }
 
     public static boolean isChild(Class baseClass, Class clazz) {
         while (clazz != null) {
             if (baseClass.equals(clazz)
                     || isInterface(baseClass, Arrays.asList(clazz
                             .getInterfaces())))
                 return true;
             clazz = clazz.getSuperclass();
         }
         return false;
     }
 
     private static Class loadClass(byte[] b) throws Exception {
         Class clazz = null;
         ClassLoader loader = Utils.class.getClassLoader();
         Class cls = Class.forName("java.lang.ClassLoader");
         java.lang.reflect.Method method = cls
                 .getDeclaredMethod("defineClass", new Class[] { String.class,
                         byte[].class, int.class, int.class });
 
         method.setAccessible(true);
         try {
             Object[] args = new Object[] { null, b, new Integer(0),
                     new Integer(b.length) };
             clazz = (Class) method.invoke(loader, args);
         } finally {
             method.setAccessible(false);
         }
         return clazz;
     }
 
     public static Class renameClass(Class clazz, String newName)
             throws Exception {
         return loadClass(makeNewFile(clazz, newName));
     }
 
     private static byte[] makeNewFile(Class clazz, String newName)
             throws IOException {
         String name = clazz.getName().replaceAll("\\.", "/") + ".class";
         InputStream stream = Utils.class.getClassLoader().getResourceAsStream(
                 name);
 
         ClassReader cr = new ClassReader(stream);
         ClassWriter cw = new ClassWriter(false);
         ClassRenamer renamer = new ClassRenamer(cw, new HashSet(), newName);
         cr.accept(renamer, false);
 
         stream.close();
 
         return cw.toByteArray();
     }
 
     public static String renameClass(Class clazz, String newName,
             String pathToSave) throws Exception {
 
         byte[] data = makeNewFile(clazz, newName);
 
         FileOutputStream fos = null;
         StringBuffer fileName = new StringBuffer(pathToSave);
         fileName.append(File.separator).append(newName).append(".class");
         try {
             fos = new FileOutputStream(fileName.toString());
             fos.write(data, 0, data.length);
         } catch (IOException ex) {
             throw ex;
         } finally {
             if (fos != null) {
                 fos.close();
             }
         }
         System.out.println(fileName.toString());
         return fileName.toString();
     }
 
     public static void addTests(TestSuite suite, Class clazz, Class testClass)
             throws Exception {
         List<Class> classList = ClassFinder.getInctance().find(clazz);
         for (Class item : classList) {
             Class testItem = testClass;
             if (classList.size() > 1) {
                 testItem = Utils.renameClass(testClass, testClass
                         .getSimpleName()
                         + "_For_" + item.getSimpleName());
             }
             Field field = testItem.getDeclaredField("testingClass");
             field.setAccessible(true);
             field.set(testItem, item);
 
             suite.addTest(new JUnit4TestAdapter(testItem));
         }
     }
 }
